package cn.bitkit.component.context;

import cn.bitkit.base.constants.BasicApiCode;
import cn.bitkit.base.container.ApiRequest;
import cn.bitkit.base.container.ApiResponse;
import cn.bitkit.base.exception.BusinessException;
import cn.bitkit.component.base.BaseService;
import cn.bitkit.component.common.ApiDataHandler;
import cn.bitkit.component.common.ValidateHandler;
import cn.bitkit.component.log.LogUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;

/**
 * @author changbo
 */
@Slf4j
public class BizServiceExecutor {

    @Async
    public <R> void asyncExecute(String serviceCode, ApiRequest<R> req){
        execute(serviceCode, req);
    }

    @SuppressWarnings("unchecked")
    public <R,S> ApiResponse<S> execute(String serviceCode, ApiRequest<R> req){
        ApiResponse<S> resp = new ApiResponse<>();
        try {
            log.info("[{}]req:{}", serviceCode, LogUtil.json(req));
            //参数校验
            ValidateHandler.checkAssert(req.getParam());
            Object service = BizServiceContext.getBizService(serviceCode);
            if(!(service instanceof BaseService)){
                throw new BusinessException(BasicApiCode.ERROR_API.code, BasicApiCode.ERROR_API.desc);
            }
            BaseService<R, S> baseService = (BaseService<R, S>) service;
            baseService.before(req.getParam());
            S result = baseService.execute(req.getParam());
            baseService.after(req.getParam(), result);
            resp.setData(result);
        } catch (Exception e) {
            log.error("[{}]", req.getTrace(), e);
            ApiDataHandler.initException(e, resp);
        }
        resp.setTrace(TraceContext.TRACE_ID.get());
        log.info("[{}]resp:{}", serviceCode, LogUtil.json(resp));
        return resp;
    }
}
